package com.share.payment.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.share.common.core.domain.R;
import com.share.common.core.exception.ServiceException;
import com.share.common.rabbit.constant.MqConst;
import com.share.common.rabbit.service.RabbitService;
import com.share.order.api.RemoteOrderInfoService;
import com.share.order.api.domain.OrderInfo;
import com.share.payment.domain.PaymentInfo;
import com.share.payment.mapper.PaymentInfoMapper;
import com.share.payment.service.IPaymentInfoService;
import com.wechat.pay.java.service.payments.model.Transaction;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

@Slf4j
@Service
@RequiredArgsConstructor
@SuppressWarnings({"unchecked", "rawtypes"})
public class PaymentInfoServiceImpl extends ServiceImpl<PaymentInfoMapper, PaymentInfo> implements IPaymentInfoService {

    private final RemoteOrderInfoService remoteOrderInfoService;

    private final RabbitService rabbitService;

    @Override
    public PaymentInfo savePaymentInfo(String orderNo) {
        // 先尝试查询是否已存在该订单的支付信息
        PaymentInfo paymentInfo = this.baseMapper.selectOne(new LambdaQueryWrapper<PaymentInfo>().eq(PaymentInfo::getOrderNo, orderNo));

        // 如果不存在则创建支付信息记录（添加幂等性保障）
        if (paymentInfo == null) {
            try {
                // 调用远程服务获取订单信息
                R<OrderInfo> orderInfoResult = remoteOrderInfoService.getByOrderNo(orderNo);
                // 检查订单信息获取是否成功
                if (R.FAIL == orderInfoResult.getCode() || orderInfoResult.getData() == null) {
                    log.error("获取订单信息失败，订单号: {}, 错误信息: {}", orderNo, orderInfoResult != null ? orderInfoResult.getMsg() : "未知错误");
                    throw new ServiceException("获取订单信息失败");
                }
                OrderInfo orderInfo = orderInfoResult.getData();

                // 创建新的支付信息对象，准备插入数据库
                paymentInfo = new PaymentInfo();
                paymentInfo.setUserId(orderInfo.getUserId());
                paymentInfo.setContent("共享充电宝租借");
                paymentInfo.setAmount(orderInfo.getTotalAmount());
                paymentInfo.setOrderNo(orderNo);
                paymentInfo.setPaymentStatus(0); // 初始状态：待支付

                // 插入支付信息记录，依赖数据库唯一索引保证幂等性
                // 若有并发请求，唯一索引会防止重复插入
                this.baseMapper.insert(paymentInfo);
            } catch (DuplicateKeyException e) {
                // 处理并发插入导致的唯一键冲突
                // 当检测到冲突时，表示可能已有其他请求成功插入记录
                log.info("检测到唯一键冲突，订单号: {} 可能已存在支付记录", orderNo);
                // 重新查询已存在的记录
                paymentInfo = this.baseMapper.selectOne(new LambdaQueryWrapper<PaymentInfo>().eq(PaymentInfo::getOrderNo, orderNo));
                // 若查询结果仍为空，说明出现异常情况
                if (paymentInfo == null) {
                    throw new ServiceException("创建支付信息失败");
                }
            } catch (Exception e) {
                // 处理其他异常情况
                log.error("创建支付信息失败，订单号: {}", orderNo, e);
                throw new ServiceException("创建支付信息失败");
            }
        }

        // 检查支付状态，若订单已关闭（状态为-1），则不允许继续操作
        if (paymentInfo.getPaymentStatus() != null && paymentInfo.getPaymentStatus().intValue() == -1) {
            throw new ServiceException("订单已关闭");
        }

        // 返回支付信息对象
        return paymentInfo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updatePaymentStatus(Transaction transaction) {
        // 查询支付记录
        PaymentInfo paymentInfo = this.baseMapper.selectOne(new LambdaQueryWrapper<PaymentInfo>().eq(PaymentInfo::getOrderNo, transaction.getOutTradeNo()));

        // 1. 幂等性处理：如果订单已支付，直接返回
        if (paymentInfo.getPaymentStatus() == 1) {
            log.info("订单已支付，无需重复处理: {}", paymentInfo.getOrderNo());
            return;
        }

        // 2. 更新支付信息
        paymentInfo.setPaymentStatus(1); // 支付状态：已支付
        paymentInfo.setOrderNo(transaction.getOutTradeNo()); // 商户订单号
        paymentInfo.setTransactionId(transaction.getTransactionId()); // 微信支付订单号
        paymentInfo.setCallbackTime(new Date()); // 回调时间
        paymentInfo.setCallbackContent(com.alibaba.fastjson.JSON.toJSONString(transaction)); // 回调内容

        // 执行更新操作
        this.updateById(paymentInfo);
        log.info("支付状态更新成功，订单号: {}", paymentInfo.getOrderNo());

        // 3. 基于MQ通知订单系统修改订单状态
        // 使用RabbitMQ发送消息，实现系统间解耦
        rabbitService.sendMessage(MqConst.EXCHANGE_PAYMENT_PAY, MqConst.ROUTING_PAYMENT_PAY, paymentInfo.getOrderNo());
        log.info("已发送支付成功消息，订单号: {}", paymentInfo.getOrderNo());
    }
}
